#ifndef __RULES__
#define __RULES__

#include <string>
#include <map>
#include "ulib.h"
#include "define.h"

using namespace std;

class CSrcSubTree {
public:
	CUString before;
	int freq;
	int num_cross;
	void Set( CUString _be, int _f, int _c )	{
		before = _be; freq = _f; num_cross = _c;
	}
	bool SaveToFile( char *fn );
	bool SaveToFile( FILE *fp );
	void Add( CUString before, int num_cross );

	int GetSize()	{ return (int)stree_map.size(); }
	void Clear()	{ stree_map.clear(); }
	int GetFreq( CUString str );

	map<string, CSrcSubTree> stree_map;
};



class CRule {
public:
	CUString before;
	CUString after;
	int freq;
};


class CRuleCross : public CRule {
public:
	int before_cross;
	int after_cross;
	bool is_best;

	CRuleCross()	{
		freq = before_cross = after_cross = NULL_NUM;
		before = after = NULL_STR;
		is_best = false;
	}

	bool LoadRule( char *fn, int cross_red_th );
	void Clear()	{ rule_map.clear();	}


	void Set( CUString _be, CUString _af, int _be_cross, int _af_cross, int _freq )	{
		before = _be; after = _af; before_cross = _be_cross; after_cross = _af_cross; freq = _freq;
	}

	virtual int GetNumRules()	{
		return (int) rule_map.size();
	}
	virtual void Add( CRuleCross &add_rule );
	virtual bool SaveToFile( FILE *fp, CSrcSubTree &stree );
	virtual bool FindRule( CUString rule_str, CRuleCross rule[], int &num_rule );

	map<string, CRuleCross> rule_map;
private:

};


class CRuleRF : public CRule {
public:
	int total_cnt;
	double prob;
	bool is_best;

	int eval_correct_cnt;
	int eval_apply_cnt;

	CRuleRF()	{
		prob = NULL_PROB;
		total_cnt = NULL_NUM;
		is_best = false;
		eval_correct_cnt = 0;
		eval_apply_cnt = 0;
	}

	bool IsReorder()	{
		CUStringList t;
		t.TokenizeByChar( after, " " );
		for( int i=0; i<t.GetSize(); i++ )	{
			CUString str = t.GetAt( i );
			str.TrimLeft("A");
			if( atoi(str.GetStr()) != i )	return true;
		}
		return false;
	}

	bool LoadRule( char *fn, int freq_th, double prob_th );
	virtual int GetNumRules() {
		return (int)rule_map.size();
	}
	virtual int GetNumBestReorderRules() {
		int num=0;
		map<string, CRuleRF>::iterator itr = rule_map.begin();
		while( itr != rule_map.end() )	{
			if( itr->second.IsReorder() == true &&
			    itr->second.is_best == true )	{
//				fprintf( stdout, "%s\t%s\n", itr->first.c_str(), itr->second.after.GetStr()  );
				num++;
			}
			itr++;
		}
		return num;
	}

	virtual void Clear()	{ rule_map.clear();	}
	virtual void Add( CRuleRF &add_rule );
	virtual bool SaveToFile( FILE *fp, CSrcSubTree &stree, bool only_reorder_best  );
	virtual bool SaveToEvalFile( FILE *fp );
	virtual bool FindRule( CUString rule_str, CRuleRF rule[], int &num_rule );

	map<string, CRuleRF> rule_map;
private:
};


class CInsertRule : public CRule {
public:
	int total_cnt;
	double prob;
	bool is_best;

	CInsertRule()	{
		prob = NULL_PROB;
		total_cnt = NULL_NUM;
		is_best = false;
	}

	bool IsInsertRule();
	void MarkBestRule();

	bool LoadRule( char *fn, int freq_th, double prob_th );
	virtual int GetNumRules() {
		return (int)rule_map.size();
	}

	/*
	virtual int GetNumBestReorderRules() {
		int num=0;
		map<string, CRuleRF>::iterator itr = rule_map.begin();
		while( itr != rule_map.end() )	{
			if( itr->second.IsReorder() == true &&
			    itr->second.is_best == true )	{
//				fprintf( stdout, "%s\t%s\n", itr->first.c_str(), itr->second.after.GetStr()  );
				num++;
			}
			itr++;
		}
		return num;
	}

	virtual bool SaveToEvalFile( FILE *fp );
	*/

	virtual void Add( CInsertRule &add_rule );
	virtual bool SaveToFile( FILE *fp, CSrcSubTree &stree, bool only_reorder_best  );
	virtual void Clear()	{ rule_map.clear();	}
	virtual bool FindRule( CUString rule_str, CInsertRule rule[], int &num_rule );

	map<string, CInsertRule> rule_map;
private:
};

#endif

